package repository

import (
	"context"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"onvif_server/internal/model"
	"sync/atomic"
)

type SubscriptionRepository interface {
	List(ctx context.Context, kw string, scopesFn ...func(*gorm.DB) *gorm.DB) (total int64, res []*model.Subscription, err error)
	Create(ctx context.Context, m *model.Subscription) error
	Update(ctx context.Context, m *model.Subscription, fields ...string) error
	GetByID(ctx context.Context, id int) (*model.Subscription, error)
	DeleteByIDs(ctx context.Context, id []int) error

	//Subscriber 返回所有的订阅者信息，有缓存,避免每次数据库存储
	Subscriber(ctx context.Context) []*model.Subscription
}

func NewSubscriptionRepository(r *Repository) SubscriptionRepository {
	return &subscriptionRepository{
		Repository: r,
	}
}

// 内存缓存订阅者列表
var subscriber = make([]*model.Subscription, 0)
var loadDb = atomic.Bool{}

type subscriptionRepository struct {
	*Repository
}

func (r *subscriptionRepository) Create(ctx context.Context, m *model.Subscription) error {
	//添加缓存
	defer func() {
		loadDb.Store(false)
	}()
	return r.DB(ctx).Create(m).Error
}

func (r *subscriptionRepository) Update(ctx context.Context, m *model.Subscription, fields ...string) error {
	//修改缓存
	defer func() {
		loadDb.Store(false)
	}()
	_db := r.DB(ctx)
	if len(fields) > 0 {
		_db = _db.Select(fields)
	}
	return _db.Where("id = ?", m.ID).Updates(m).Error
}

func (r *subscriptionRepository) GetByID(ctx context.Context, id int) (m *model.Subscription, err error) {
	err = r.DB(ctx).Where("id = ?", id).First(&m).Error
	return
}

func (r *subscriptionRepository) DeleteByIDs(ctx context.Context, ids []int) error {
	defer func() {
		loadDb.Store(false)
	}()
	return r.DB(ctx).Delete(&model.Subscription{}, ids).Error
}

// List 获取列表
func (r *subscriptionRepository) List(ctx context.Context, kw string, scopesFn ...func(*gorm.DB) *gorm.DB) (total int64, res []*model.Subscription, err error) {
	db := r.DB(ctx).Model(&model.Subscription{})
	if kw != "" {
		_k := "%" + kw + "%"
		db.Where("app_name like ? ", _k)
	}
	err = db.Count(&total).Error
	if err != nil || total == 0 {
		return
	}
	err = db.Scopes(scopesFn...).Find(&res).Error
	return
}

// Subscriber 获取订阅者列表， 会缓存
func (r *subscriptionRepository) Subscriber(ctx context.Context) []*model.Subscription {
	if !loadDb.Load() {
		err := r.DB(ctx).Model(&model.Subscription{}).Find(&subscriber).Error
		if err != nil {
			r.log.Error("subscriptionRepository Subscriber() error", zap.Error(err))
			return subscriber
		}
		loadDb.Store(true)
	}
	return subscriber
}
